﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

namespace Asteroids.Game
{
    public class EntityBase : IUpdate, IRender, ICollide
    {
        public bool Dead { get; set; }
        public PolarCoordinate Velocity { get; set; }
        public double FaceDirection { get; set; }
        public List<PolarCoordinate> VertexData { get; set; }

        public Brush Brush { get; set; }

        public virtual bool IsVulnerable()
        {
            return false;
        }

        public Coordinate Location { get; set; }
        public double Radius { get; set; }

        public EntityBase()
        {
            VertexData = new List<PolarCoordinate>();
            Location = new Coordinate(150, 150);
            Dead = false;
            Velocity = new PolarCoordinate(0.0, 0.0);
            Brush = Brushes.White;
        }

        public virtual void Update(UpdateEventArgs e)
        {
            Location += (Coordinate)Velocity;
            Location.X = Wrap(Location.X, 0, MainWindow.Instance.ActualWidth);
            Location.Y = Wrap(Location.Y, 0, MainWindow.Instance.ActualHeight);
            FaceDirection = Wrap(FaceDirection, 0, Math.PI*2);
            Velocity.Angle = Wrap(Velocity.Angle, 0, Math.PI*2);
        }

        private static double Wrap(double t, double min, double max)
        {
            while (t >= min)
            {
                t -= (max - min);
            }
            t += (max - min);
            return t;
        }

        public virtual Canvas Render(RenderEventArgs e)
        {
            var lineList = new List<Shape>();
            if (VertexData.Count != 0 && !Dead)
            {
                for (int i = 1; i < VertexData.Count; i++)
                {
                    lineList.Add(new Line()
                    {
                        X1 = VertexData[i-1].Magnitude * Math.Cos(VertexData[i-1].Angle + FaceDirection) + Location.X,
                        Y1 = VertexData[i-1].Magnitude * Math.Sin(VertexData[i-1].Angle + FaceDirection) + Location.Y,
                        X2 = VertexData[i].Magnitude * Math.Cos(VertexData[i].Angle + FaceDirection) + Location.X,
                        Y2 = VertexData[i].Magnitude * Math.Sin(VertexData[i].Angle + FaceDirection) + Location.Y,
                        Stroke = Brush,
                        StrokeThickness = 2
                    });
                }
                lineList.Add(new Line()
                {
                    X1 = VertexData[VertexData.Count - 1].Magnitude * Math.Cos(VertexData[VertexData.Count - 1].Angle + FaceDirection) + Location.X,
                    Y1 = VertexData[VertexData.Count - 1].Magnitude * Math.Sin(VertexData[VertexData.Count - 1].Angle + FaceDirection) + Location.Y,
                    X2 = VertexData[0].Magnitude * Math.Cos(VertexData[0].Angle + FaceDirection) + Location.X,
                    Y2 = VertexData[0].Magnitude * Math.Sin(VertexData[0].Angle + FaceDirection) + Location.Y,
                    Stroke = Brush,
                    StrokeThickness = 2
                });
            }

            var retCanvas = new Canvas();
            foreach (var line in lineList)
            {
                retCanvas.Children.Add(line);
            }

            return retCanvas;
        }

        public virtual void Collide(CollideEventArgs e)
        {
        }

        public bool TestCollideWith(ICollide collidable)
        {
            return IsWithinOf(Radius + collidable.Radius, collidable);
        }

        public bool IsWithinOf(double range, ICollide collidable)
        {
            return range > Math.Sqrt(Math.Pow(Location.X - collidable.Location.X, 2) +
                                     Math.Pow(Location.Y - collidable.Location.Y, 2));
        }
    }
}
